

/**
 * \file
 *  Low level functions to support stdio and dynamic memory functionality
 * 
*/


#include <errno.h>
#include <reent.h>
#include <sys/stat.h>
#include <stdint.h>

#include "utils/swupdate.h"
#include "utils/uartstdio.h"


/** \fn _ssize_t _read_r(struct _reent *r, int file, void *ptr, size_t len)
 * Reroute reentrant version of read() to FATFileRead.
 * \param r Not used
 * \param file File handle to read
 * \param ptr Pointer to data buffer
 * \param len Bytes to read
 * \return Bytes read
 * 
 */
_ssize_t _read_r(
    struct _reent *r, 
    int file, 
    void *ptr, 
    size_t len)
{
/*	char c;
	int  i;
	unsigned char *p;

	if (file < 3)
	{
		p = (unsigned char*)ptr;
		
		for (i = 0; i < len; i++) {
			while ( !uart0_kbhit() ) ;
			c = (char) uart0_getc();
			if (c == 0x0D) {
				*p='\0';
				break;
			}
			*p++ = c;
			uart0_putc(c);
		}
		return len - i;
	}
	else
	{
//		printf("__read_r_\n");
		return FATFileRead(file,ptr,len);
	}
	*/
	return 0;
}

/** \fn _ssize_t _write_r (struct _reent *r, int file, const void *ptr, size_t len)
 * Reroute reentrant version of write() to FATFileWrite.
 * \param r Not used
 * \param file File handle to write
 * \param ptr Pointer to data buffer
 * \param len Bytes to write
 * \return Bytes written
 * 
 */
_ssize_t _write_r (
    struct _reent *r, 
    int file, 
    const void *ptr, 
    size_t len)
{
/*	int i;
	const unsigned char *p;
	
	if (file < 3)
	{
		p = (const unsigned char*) ptr;
		
		for (i = 0; i < len; i++) {
			if (*p == '\n' ) uart0_putc('\r');
			uart0_putc(*p++);
		}
		return len;
	}
	else
		//return FATFileWrite(file,ptr,len);
*/

		return -1;
}


/** \fn int _open_r( struct _reent *reent, const char *file, int flags, int mode)
 * Reroute reentrant version of open() to FATFileOpen.
 * \param reent Not used
 * \param file File name to open
 * \param flags Access flags
 * \param mode Not used
 * \return File handle
 * 
 */
int _open_r(
 	struct _reent *reent,
    const char *file, 
    int flags, 
    int mode)
{
	//printf("__open_r_\n");
	/*if (file < 3)
		return -1;
	else
	*/
	//return FATFileOpen(file,flags);
	return -1;
}


/** \fn int _close_r(struct _reent *r, int file)
 * Reroute reentrant version of close() to FATFileClose.
 * \param r Not used
 * \param file File handle to close
 * \return Error code
 * 
 */
int _close_r(
    struct _reent *r, 
    int file)
{
	/*if (file < 3)
		return 0;
	else
		return FATFileClose(file);*/
	return 0;
}


/** \fn _off_t _lseek_r(struct _reent *r, int file, _off_t ptr, int dir)
 * Reroute reentrant version of lseek() to FATFileSeek.
 * \param r Not used
 * \param file File handle to seek in
 * \param ptr Offset pointer
 * \param dir Direction to seek
 * \return New offset pointer
 * 
 */
_off_t _lseek_r(
    struct _reent *r, 
    int file, 
    _off_t ptr, 
    int dir)
{
	//return FATSeek(file, ptr, dir);
	return 0;
}


/** \fn int _fstat_r(struct _reent *r, int file, struct stat *st)
 * Not used so far.
 * \param r Not used
 * \param file File handle
 * \param st Not used
 * \return Not used
 * 
 */
int _fstat_r(
    struct _reent *r, 
    int file, 
    struct stat *st)
{
	/*  Always set as character device.				*/
	st->st_mode = S_IFCHR;
	/* assigned to strong type with implicit 	*/
	/* signed/unsigned conversion.  Required by 	*/
	/* newlib.					*/

	return 0;
}


/** \fn int isatty(int file)
 * Not used.
 * \param file File handle
 * \return Error code
 * 
 */
int isatty(int file); /* avoid warning */

int isatty(int file)
{
	if (file < 3)
		return 1;
	return 0;
}


/** \fn int read(int file, char *ptr, int len)
 * Reroute read() to FATFileRead.
 * \param file File handle to read
 * \param ptr Pointer to data buffer
 * \param len Bytes to read
 * \return Bytes read
 * 
 */
int read(int file, char *ptr, int len)
{
    //printf("_read_\n");
	//return FATFileRead(file,ptr,len);
	return 0;
}


/** \fn int write(int file, char *ptr, int len)
 * Reroute write() to FATFileWrite.
 * \param file File handle to write
 * \param ptr Pointer to data buffer
 * \param len Bytes to write
 * \return Bytes written
 * 
 */
int write(int file, char *ptr, int len)
{
/*	int i;
	const unsigned char *p;
	
    //printf("_write_\n");
	if (file < 3)
	{
		p = (const unsigned char*) ptr;
		
		for (i = 0; i < len; i++) {
			if (*p == '\n' ) uart0_putc('\r');
			uart0_putc(*p++);
		}
		return len;
	}
	else
		//return FATFileWrite(file,ptr,len);
		return -1;
*/
	return -1;
}



/** \fn int lseek(int file, int ptr, int dir)
 * Reroute lseek() to FATFileSeek.
 * \param file File handle to seek in
 * \param ptr Offset pointer
 * \param dir Direction to seek
 * \return New offset pointer
 * 
 */
int lseek(int file, int ptr, int dir)
{
	//printf("_lseek_\n");
	//return FATSeek(file, ptr, dir);
	return 0;
}


/** \fn int open(const char *name, int flags, int mode)
 * Reroute open() to FATFileOpen.
 * \param name File name to open
 * \param flags Access flags
 * \param mode Not used
 * \return File handle
 * 
 */
int open(const char *name, int flags, int mode)
{
	//printf("_open_\n");
    //return FATFileOpen(name,flags);
	return -1;
}




int _kill(int pid, int sig)
{
	pid = pid; sig = sig; // avoid warnings
	errno = EINVAL;
	return -1;
}

void _exit(int status)
{
 	status = status;	// avoid warning
 	while(1) {;}		// lockup
}

int _getpid(void)
{
 	return 1;
}


//!
//! Get Main Stack Pointer.
//!
uint32_t __get_MSP(void)
{
	uint32_t result=0;
	__asm volatile ("MRS %0, msp" : "=r" (result) );
	return(result);
}

//!
//! _end is set in the linker file to point to
//! the end of allocated space (data + bss)
//!
extern char _end;


static char *heap_end;	// local var

char* get_heap_end(void)
{
	return (char*) heap_end;
}

char* get_stack_top(void)
{
	return (char*) __get_MSP();
}


 caddr_t _sbrk(int incr)
 {
 	char *prev_heap_end;

 	//printf("_sbrk called with incr %d\n", incr);
 	//printf("heap_end = %08x\n", heap_end);

 	if (heap_end == 0)
 	{
 		heap_end = &_end;	// initialize heap_end of first call
 	}
 	prev_heap_end = heap_end;

 	//
 	// check to see if heap_end has reached the stack
 	if (heap_end + incr > get_stack_top())
 	{
 		printf("Heap and stack collision\n");
 		_exit(1);
 	}

 	heap_end += incr;

 	return (caddr_t) prev_heap_end;
 }



